#include "VoronoiParser.h"
#include <algorithm>

using namespace voronoi;
using namespace std;

bool VoronoiParser::isPolyFrontier(int x, int y) const
{
	unsigned int p = readPoint(x,y);
	unsigned int foundP = p;
	int numfound = 0;
	if(p==0xFFFFFF) // el blanco es el fondo
		return false;

	unsigned int pv[8];
	read8Neighbours(x,y, pv); 

	for(int i=0;i<8;++i)
		if(p!=pv[i] && foundP!=pv[i])
		{
			++numfound;
			foundP = pv[i];
			if(numfound>1) // at least 2 different neighbours
				return true;
		}

	return false;
}

Face VoronoiParser::getConnectedVertexPixels(int xpos, int ypos)
{
	std::set<PixelPos> toRemoveNow;
	std::set<PixelPos> toRemoveNext;
	toRemoveNow.insert(PixelPos(xpos,ypos));

	Face result;

	while(toRemoveNow.size() > 0)
	{
		std::set<PixelPos>::iterator it = toRemoveNow.begin();
		std::set<PixelPos>::iterator end= toRemoveNow.end();
		for(;it!=end;++it)
		{
			const PixelPos &vnow = *it;
			m_flags[vnow.x + vnow.y*m_width] = false;
			result.insert(readPoint(vnow.x,vnow.y));

			for(int x=-1;x<=1;++x)
				for(int y=-1;y<=1;++y)
						if(readFlag(vnow.x+x, vnow.y+y))
							toRemoveNext.insert(PixelPos(vnow.x+x,vnow.y+y));
		}
		toRemoveNow = toRemoveNext;
		toRemoveNext.clear();
	}
	return result;
}

void VoronoiParser::parse(std::set<Face> * faces)
{
	std::vector< std::vector<unsigned int> >result;
	// locate pixels with neighbours of two different colors and mark them as "vertex pixels"
	for(int y=0;y<m_height;++y)
		for(int x=0;x<m_width;++x)
			if(isPolyFrontier(x,y))
				m_flags[x + y*m_width] = true;

	//	get the connected components of vertex pixels. Each of them will be a polygon in the triangulation
	for(int y=0;y<m_height;++y)
		for(int x=0;x<m_width;++x)
			if(m_flags[x + y*m_width])
				faces->insert(getConnectedVertexPixels(x,y));
}

VoronoiParser::VoronoiParser(unsigned int* pixels, int width, int height):m_pixels(pixels)
{
	m_width = width;
	m_height = height;
	m_flags = new bool[width*height];
	memset(m_flags, 0, sizeof(bool) * width*height);
}

VoronoiParser::~VoronoiParser()
{
	delete[] m_flags;
}


